package com.jason.kotlinstudy.aspect;

import android.os.SystemClock;
import android.util.Log;

import com.jason.kotlinstudy.utils.StopWatch;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

/**
 * Aspect representing the cross cutting-concern: Method and Constructor Tracing.
 * 侵入式的编译注解
 * 侵入式用法，一般会使用自定义注解，以此作为选择切入点的 Pointcut 规则。
 */
@Aspect
public class TraceAspect {
    /**
     * 针对所有继承 Activity 类的 onCreate 方法
     */
    @Pointcut("execution(* android.app.Activity+.onCreate(..))")
    public void activityOnCreatePointcut() {

    }


    //被"org.android10.gintonic.annotation.DebugTrace"标记的方法。
    //针对带有DebugTrace注解的方法
    @Pointcut("execution(@com.jason.kotlinstudy.annotation.DebugTrace * *(..))")
    public void methodAnnotatedWithDebugTrace() {


    }

    //被"org.android10.gintonic.annotation.DebugTrace"标记的构造器。
    @Pointcut("execution(@com.jason.kotlinstudy.annotation.DebugTrace *.new(..))")
    public void constructorAnnotatedDebugTrace() {

    }

    /**
     * 我们定义的 "weaveJointPoint(ProceedingJoinPoint joinPoint)"
     * 这个方法被添加了"@Around"注解，这意味着我们的代码注入将发生在被
     * "@DebugTrace"注解标记的方法前后。
     * 在用DebugTrace注解修饰的方法或者构造函数里面注入如下代码。
     */
    @Around("methodAnnotatedWithDebugTrace() || constructorAnnotatedDebugTrace() || activityOnCreatePointcut()")
    public Object saveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String className = methodSignature.getDeclaringType().getSimpleName();
        String methodName = methodSignature.getName();
        final StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Object result = joinPoint.proceed();
        stopWatch.stop();
        Log.d("TAG", className + "--" + buildLogMessage(methodName, stopWatch.getTotalTimeMillis()));
        return result;
    }

    /**
     * Create a log message.
     *
     * @param methodName     A string with the method name.
     * @param methodDuration Duration of the method in milliseconds.
     * @return A string representing message.
     */
    private static String buildLogMessage(String methodName, long methodDuration) {
        StringBuilder message = new StringBuilder();
        message.append("Gintonic --> ");
        message.append(methodName);
        message.append(" --> ");
        message.append("[");
        message.append(methodDuration);
        message.append("ms");
        message.append("]");

        return message.toString();
    }
}
